package com.bwie.service.impl;

import cn.hutool.core.io.file.FileNameUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.config.KafkaConfig;
import com.bwie.mapper.TbLogMapper;
import com.bwie.pojo.TbLog;
import com.bwie.pojo.TbUser;
import com.bwie.pojo.TbUserRole;
import com.bwie.service.TbUserService;
import com.bwie.mapper.TbUserMapper;
import com.bwie.utils.MobileMessageUtil;
import com.bwie.utils.R;
import com.bwie.vo.LoginVo;
import com.bwie.vo.PageInfoVo;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
* @author Lenovo
* @description 针对表【tb_user】的数据库操作Service实现
* @createDate 2025-03-21 18:07:41
*/
@Service
public class TbUserServiceImpl extends ServiceImpl<TbUserMapper, TbUser>
    implements TbUserService{

    @Autowired
    private TbUserMapper tbUserMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    FastFileStorageClient fastFileStorageClient;
    @Autowired
    HttpServletRequest request;
    @Autowired
    KafkaTemplate kafkaTemplate;
    @Autowired
    private TbLogMapper tbLogMapper;

    @Override
    public R getUserById(int userId) {
        TbUser tbUser = tbUserMapper.selectById(userId);
        if(tbUser == null){
            return R.ERROR(404,"用户不存在");
        }
        return R.OK(tbUser);
    }

    @Override
    public R login(LoginVo loginVo) {
        //判断用户是否存在
        TbUser tbUser = tbUserMapper.selectOne(new LambdaQueryWrapper<TbUser>().eq(TbUser::getUserName, loginVo.getUserName()));
        if(tbUser==null){
            return R.ERROR(404,"用户不存在");
        }
        //密码是否正确
        if(!tbUser.getUserPass().equals(loginVo.getUserPass())){
            return R.ERROR(500,"密码错误");
        }
        //缓存token
        String token = Jwts.builder().signWith(SignatureAlgorithm.HS256,"123456")
                .claim("userId", tbUser.getUserId())
                .claim("useName", tbUser.getUserName())
                .claim("realName", tbUser.getRealName()).compact();
        String tokenKey = "token-" + tbUser.getUserId();
        redisTemplate.opsForValue().set(tokenKey,token,60, TimeUnit.MINUTES);
        //返回信息
        tbUser.setUserPass(null);
        tbUser.setToken(token);
        return R.OK(tbUser);
    }

    @Override
    public R getUserList(PageInfoVo pageInfoVo) {

        String token = request.getHeader("token");
        if(token == null){
            return R.ERROR(500,"请先登录");
        }
        Claims body = Jwts.parser().setSigningKey("123456").parseClaimsJws(token).getBody();
        Integer userId = body.get("userId", Integer.class);

        List<TbUserRole> roleList = tbUserMapper.getUserRole(userId);
        Boolean isAdmin = false;
        for (TbUserRole tbUserRole : roleList) {
            if(tbUserRole.getRoleName().equals("管理员")){
                isAdmin = true;
                break;
            }
        }

        //定义分页参数
        Page<TbUser> page = new Page<>(pageInfoVo.getPageNum(), pageInfoVo.getPageSize());
        //获取分页数据
        LambdaQueryWrapper<TbUser> wrapper = new LambdaQueryWrapper<>();
        if(!isAdmin){
            //不是管理员，只查自己
            wrapper.eq(TbUser::getUserId,userId);
        }
        //添加搜索条件
        if(StringUtils.isNotBlank(pageInfoVo.getKeyWord())){
            //模糊查询=====关键字
            wrapper.like(TbUser::getUserName,pageInfoVo.getKeyWord())
                    .or()
                    .like(TbUser::getRealName,pageInfoVo.getKeyWord())
                    .or()
                    .like(TbUser::getUserMobile,pageInfoVo.getKeyWord())
                    .or()
                    .like(TbUser::getUserEmail,pageInfoVo.getKeyWord());
        }
        wrapper.orderByDesc(TbUser::getUserId);

        Page<TbUser> tbUserPage = tbUserMapper.selectPage(page,wrapper);
        //返回分页数据
        return R.OK(tbUserPage);
    }

    @Override
    public R addUser(TbUser tbUser) {
        LambdaQueryWrapper<TbUser> wrapper = new LambdaQueryWrapper<TbUser>().eq(TbUser::getUserName, tbUser.getUserName());
        TbUser user = tbUserMapper.selectOne(wrapper);
        if(user != null){
            return R.ERROR(500,"用户已存在");
        }
        tbUserMapper.insert(tbUser);
        return R.OK();
    }

    @Override
    public R uploadImage(MultipartFile file) {
        try {
            String extName = FileNameUtil.extName(file.getOriginalFilename());
            StorePath storePath = fastFileStorageClient.uploadFile(file.getInputStream(), file.getSize(), extName, null);
            if(storePath == null){
                return R.ERROR(500,"上传失败");
            }
            String url = "http://192.168.80.192:8888/" + storePath.getFullPath();
            return R.OK(url);
        } catch (IOException e) {
            e.printStackTrace();
            return R.ERROR(500,"上传失败");
        }
    }

    @Override
    public R getUserRole(Integer userId) {
        List<TbUserRole> list = tbUserMapper.getUserRole(userId);
        return R.OK(list);
    }

    @Override
    public R checkUser(TbUser tbUser) {
        //如果驳回，必须输入驳回原因
        if(tbUser.getCheckStatus() == 2){
            if(StringUtils.isEmpty(tbUser.getCheckReason())){
                return R.ERROR(500,"驳回原因不能为空");
            }
        }
        //更新用户状态
        tbUserMapper.updateById(tbUser);

        //驳回，发送消息+记录日志
        if(tbUser.getCheckStatus() == 2){
            //发送kafka发送消息
            String msg = JSON.toJSONString(tbUser);
            System.out.println("发送消息："+msg);
            kafkaTemplate.send(KafkaConfig.TOPIC_LOG,msg);
        }
        return R.OK();
    }

    @Override
    public R updateUser(TbUser tbUser) {
        TbUser user = tbUserMapper.selectOne(
                new LambdaQueryWrapper<TbUser>().eq(TbUser::getUserName, tbUser.getUserName())
        );
        if(user == null){
            return R.ERROR(404,"用户不存在");
        }
        tbUserMapper.updateById(tbUser);
        return R.OK();
    }

    @Override
    public R deleteUserById(Integer userId) {
        TbUser tbUser = tbUserMapper.selectById(userId);
        if(tbUser == null){
            return R.ERROR(404,"用户不存在");
        }
        tbUserMapper.deleteById(userId);
        return R.OK();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R deleteBatch(List<TbUser> userList) {
        for (TbUser tbUser : userList) {
            tbUserMapper.deleteById(tbUser.getUserId());
        }
        return R.OK();
    }

    @KafkaListener(topics = KafkaConfig.TOPIC_LOG)
    public void recvKafkaMsg(String msg, Acknowledgment acknowledgment){
        System.out.println("接收消息："+msg);

        TbUser tbUser = JSON.parseObject(msg, TbUser.class);

        //获取手机号
        String mobile = tbUser.getUserMobile();
        String content = "您的账号为："+tbUser.getUserName()+"审核已通过";
        if(tbUser.getCheckStatus() == 2){
            content = "您的账号为："+tbUser.getUserName()+"审核已驳回，原因是："+tbUser.getCheckReason();
        }

        //发送短信
        MobileMessageUtil.sendMobileMessage(mobile,content);

        //记录日志
        TbLog tbLog = new TbLog();
        tbLog.setLogContent(content);
        tbLog.setLogTime(new Date());

        tbLogMapper.insert(tbLog);

        //手动确认消息，删除消息
        acknowledgment.acknowledge();
        System.out.println("消息已确认");
    }
}

